"""Field

 [...], {type, readonly, ...}, rename(None/name)
"""
import re
import itertools
from collections import OrderedDict
from pprint import pprint

from jinja2 import Template

from models import items
from templates.validator import HEAD, TEMPLATE, TEMPLATE_INSTANCE
from utils import columnsplit


TYPES = {
    'Integer': 'integer',
    'Date': 'date',
    'DateTime': 'datetime',
    'Text': 'string',
    'URL': 'string',
    'JSON': 'dict',
    'UUID': 'string',
}

COERCIONS = {
    'Integer': 'int',
    'Date': 'strtodate',
    'DateTime': 'strtodatetime',
}

REGEXS = {
    'UUID': 'uuid_regex',
}


def codegen():
    regex4docs = re.compile('(\s*\|.*)$', re.M)
    
    template = Template(TEMPLATE)
    template_instance = Template(TEMPLATE_INSTANCE)
    
    codes = [HEAD]
    instances = []
    
    for item in items:
        title = item['title']
        classname = item['classname']
        # (attr, validator)
        columns = columnsplit(item['columns'])
        columns = [tuple(itertools.compress(x, [1, 0, 1])) for x in columns]

        docs = regex4docs.sub('', item['columns'])
        if 'docs' in item:
            docs += item['docs']
        docs = docs.replace('\n', '\n{}'.format(' '*4))

        rules = []
        rename_rules = []
        for row in columns:
            rule = OrderedDict()
            rename_rule = None

            name, type_ = row[0][1], row[0][2]

            # type
            rule['type'] = "'{}'".format(TYPES[type_])  # HAL-TYPE
            # others
            if row[1][0] != '-':
                for attr in [i.strip() for i in row[1][0].split(',')]:
                    # readonly 
                    if attr in ('readonly'):
                        rule[attr] = True
            if 'readonly' not in rule:
                # coerce
                if type_ in COERCIONS:
                    rule['coerce'] = COERCIONS[type_]
                # regex
                if type_ in REGEXS:
                    rule['regex'] = REGEXS[type_]
                # rename
                if name != name.lower():
                    rename_rule = name

            rules.append(rule)
            rename_rules.append(rename_rule)
    
        columns = tuple(zip((i[0] for i in columns), rules, rename_rules))
        code = template.render(title=title,
                               docs=docs,
                               classname=classname,
                               columns=columns)
        codes.append(code)
        instances.append(template_instance.render(classname=classname))


    with open('gen/validators.py', 'w') as f:
        for s in codes:
            f.write(s)
        for s in instances:
            f.write(s)


if __name__ == '__main__':
    codegen()
